package cc.shacocloud.mirage.utils.reflection;

import cc.shacocloud.mirage.utils.KotlinDetector;
import kotlin.reflect.KFunction;
import kotlin.reflect.KParameter;
import kotlin.reflect.jvm.ReflectJvmMapping;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

/**
 * {@link ParameterNameDiscoverer} 实现，它使用 Kotlin 的反射工具来内省参数名称
 */
public class KotlinReflectionParameterNameDiscoverer implements ParameterNameDiscoverer {
    
    @Nullable
    @Override
    public String[] getParameterNames(@NotNull Method method) {
        if (!KotlinDetector.isKotlinType(method.getDeclaringClass())) {
            return null;
        }
        
        try {
            KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
            return (function != null ? getParameterNames(function.getParameters()) : null);
        } catch (UnsupportedOperationException ex) {
            return null;
        }
    }
    
    @Nullable
    @Override
    public String[] getParameterNames(@NotNull Constructor<?> ctor) {
        if (ctor.getDeclaringClass().isEnum() || !KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
            return null;
        }
        
        try {
            KFunction<?> function = ReflectJvmMapping.getKotlinFunction(ctor);
            return (function != null ? getParameterNames(function.getParameters()) : null);
        } catch (UnsupportedOperationException ex) {
            return null;
        }
    }
    
    @Nullable
    private String[] getParameterNames(@NotNull List<KParameter> parameters) {
        List<KParameter> filteredParameters = parameters
                .stream()
                // 必须包含扩展方法的扩展接收器，因为它们在 Java 中显示为普通方法参数
                .filter(p -> KParameter.Kind.VALUE.equals(p.getKind()) || KParameter.Kind.EXTENSION_RECEIVER.equals(p.getKind()))
                .collect(Collectors.toList());
        String[] parameterNames = new String[filteredParameters.size()];
        for (int i = 0; i < filteredParameters.size(); i++) {
            KParameter parameter = filteredParameters.get(i);
            // 扩展接收器没有明确命名，但需要为 Java 提供名称 互操作性接收器不是有效的 Kotlin 标识符，但在 Java 中有效，因此可以在此处使用
            String name = KParameter.Kind.EXTENSION_RECEIVER.equals(parameter.getKind()) ? "$receiver" : parameter.getName();
            if (name == null) {
                return null;
            }
            parameterNames[i] = name;
        }
        return parameterNames;
    }
    
}
